home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Gfx / Icon / itools_2.01.lha / icontools-2.01 / opticon.c < prev    next >
C/C++ Source or Header  |  1995-08-06  |  18KB  |  710 lines

  1. /*                                                               -*- C -*-
  2.  *  OPTICON.C
  3.  *
  4.  *  (c)Copyright 1994 by Tobias Ferber,  ukjg@rz.uni-karlsruhe.de
  5.  *
  6.  *  This file is part of the IconTools distribution
  7.  *
  8.  *  OptIcon is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published
  10.  *  by the Free Software Foundation; either version 1 of the License,
  11.  *  or (at your option) any later version.
  12.  *
  13.  *  OptIcon is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* $VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $ */
  24.  
  25. #include "version.h"
  26. static char versiontag[] = "$VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $";
  27.  
  28. /* Compile w/ -DDEBUG to output more information at runtime */
  29.  
  30. #include <ctype.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34.  
  35. #include <exec/types.h>
  36. #include <exec/memory.h>
  37.  
  38. #include <dos/dos.h>
  39. #include <dos/rdargs.h>
  40.  
  41. #include <intuition/intuition.h>
  42. #include <intuition/intuitionbase.h>
  43.  
  44. #include <workbench/workbench.h>
  45. #include <workbench/startup.h>
  46. #include <workbench/icon.h>
  47.  
  48. #include "memfn.h"
  49.  
  50. #ifdef __GNUC__
  51. /* suggest parentheses around assignment used as truth value */
  52. #define if(assignment) if( (assignment) )
  53. #endif /* __GNUC__ */
  54.  
  55. extern struct Library *OpenLibrary(STRPTR, ULONG);
  56. extern void CloseLibrary(struct Library *);
  57. extern void CopyMem(APTR, APTR, ULONG);
  58. extern void *AllocMem(ULONG, ULONG);
  59. extern void FreeMem(void *, ULONG);
  60. extern ULONG TypeOfMem(void *);
  61. extern struct RDArgs *ReadArgs(STRPTR, LONG *, struct RDArgs *);
  62. extern LONG IoErr(void);
  63. extern BOOL PrintFault(LONG, STRPTR);
  64. extern BPTR Lock(STRPTR, LONG);
  65. extern void UnLock(BPTR);
  66. extern void FreeArgs(struct RDArgs *);
  67. extern struct DiskObject *GetDiskObject(char *);
  68. extern BOOL PutDiskObject(char *, struct DiskObject *);
  69. extern void FreeDiskObject(struct DiskObject *);
  70.  
  71. struct IconBase *IconBase;
  72.  
  73. void display_version_information(void)
  74. {
  75.   static char license[]=
  76.     "OptIcon is free software; you can redistribute it and/or modify\n"
  77.     "it under the terms of the GNU General Public License as published\n"
  78.     "by the Free Software Foundation; either version 1 of the License,\n"
  79.     "or (at your option) any later version.\n"
  80.     "\n"
  81.     "OptIcon is distributed in the hope that it will be useful,\n"
  82.     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  83.     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  84.     "GNU General Public License for more details.\n"
  85.     "\n"
  86.     "You should have received a copy of the GNU General Public License\n"
  87.     "along with OptIcon; see the file COPYING.  If not, write to the\n"
  88.     "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
  89.     ;
  90.  
  91.   puts("\nOptIcon Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n"
  92.        "(c)Copyright 1994,95 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de\n");
  93.  
  94.   puts(license);
  95. }
  96.  
  97.  
  98. struct Image *free_image(struct Image *i)
  99. {
  100.   if(i)
  101.   {
  102.     long size= i->Depth * i->Height * ((i->Width + 15) / 16) * sizeof(UWORD);
  103.  
  104.     if(i->ImageData && size > 0)
  105.       FreeMem( i->ImageData, size );
  106.  
  107.     FreeMem( i, sizeof(struct Image) );
  108.   }
  109.  
  110.   return (struct Image *)0L;
  111. }
  112.  
  113. /* command line options */
  114. #define OPT_NOEXPAND  (1<<0)
  115. #define OPT_CRITICAL  (1<<1)
  116. #define OPT_VERBOSE   (1<<2)
  117. #define OPT_REMAPV37  (1<<3)
  118.  
  119. struct Image *optimize_image(struct Image *i, WORD planes, int optimode)
  120. {
  121.   UWORD p16= i->Height * ((i->Width + 15) / 16); /* #of words per plane */
  122.   UWORD *idata= i->ImageData;
  123.   WORD d, dmax, D, P;
  124.   UBYTE pp= 0;    /* plane pick */
  125.   UBYTE p10= 0;   /* plane on/off */
  126.  
  127.   struct Image *o= i;  /* optimized image */
  128.  
  129.   /* prevent silly args from being harmful */
  130.  
  131.   if(!i)
  132.     return i;
  133.  
  134.   if(planes > 8)
  135.     planes= 8;
  136.  
  137.   if(optimode & OPT_VERBOSE)
  138.   {
  139.     printf("(depth=%d, pick=%d, onoff=%d)", i->Depth,
  140.                                             i->PlanePick,
  141.                                             i->PlaneOnOff);
  142.     fflush(stdout);
  143.   }
  144.  
  145.   /*
  146.       PRESCAN:  Examine dmax planes of i and compute
  147.  
  148.         D   = the real depth (without trailing 0 planes)
  149.         pp  = the new PlanePick value
  150.         p10 = the new PlaneOnOff value
  151.   */
  152.  
  153.   dmax= (0 < planes && planes < i->Depth) ? planes : i->Depth;
  154.  
  155.   for(d= D= 0; d<dmax; d++)
  156.   {
  157.     /* check if we have some image data for plane d */
  158.     if(i->PlanePick & (1<<d))
  159.     {
  160.       UWORD n, *p, v;
  161.  
  162.       /* scan the image data of plane d */
  163.       for(n=0, p=idata, v=*p; n < p16; n++, p++)
  164.         if(*p != v)
  165.           break;
  166.  
  167.       if(n==p16 && v==0xFFFF) /* plane d is entirely 1 */
  168.         p10 |= (1<<d);  /* pp bit is already 0 */
  169.  
  170.       if( n!=p16 || (n==p16 && v!=0x0000 && v!=0xFFFF) )
  171.         pp |= (1<<d);
  172.  
  173.       if( n!=p16 || (n==p16 && v!=0x0000) )
  174.         D= d;
  175.  
  176.       idata= &idata[p16];
  177.     }
  178.     else if(i->PlaneOnOff & (1<<d))
  179.     {
  180.       p10 |= (1<<d);
  181.       D=d;
  182.     }
  183.   }
  184.  
  185.   ++D;
  186.  
  187.   if( (optimode & OPT_VERBOSE) && (D != dmax || pp != i->PlanePick || p10 != i->PlaneOnOff) )
  188.   {
  189.     printf(" -> (%d,%d,%d)", D,pp,p10);
  190.     fflush(stdout);
  191.   }
  192.  
  193.   /* compute the #of planes in the output image */
  194.   P= ( planes>D && !(optimode & OPT_NOEXPAND) ) ? planes : D;
  195.  
  196.   if(P != i->Depth || pp != i->PlanePick || p10 != i->PlaneOnOff)
  197.   {
  198.     UWORD p8= p16 * sizeof(UWORD);
  199.     UWORD *odata;
  200.     ULONG osize= P * p8;
  201.  
  202.     if( o= (struct Image *)AllocMem(sizeof(struct Image),MEMF_CLEAR) )
  203.     {
  204.       if( odata= (UWORD *)AllocMem(osize,TypeOfMem(i->ImageData)|MEMF_CLEAR) )
  205.       {
  206.         CopyMem( (APTR)i, (APTR)o, sizeof(struct Image) );
  207.         o->ImageData= odata;
  208.  
  209.         idata= i->ImageData;
  210.  
  211.         for(d=0; d<D; d++)
  212.         {
  213.           if( pp & (1<<d) )
  214.           {
  215.             if(i->PlanePick & (1<<d))
  216.             {
  217.               CopyMem( (APTR)idata, (APTR)odata, p8 );
  218.               idata= &idata[p16];
  219.               odata= &odata[p16];
  220.             }
  221.             else /* !PlanePick bit (should not happen) */
  222.             {
  223.               memset( (char *)odata, (i->PlaneOnOff & (1<<d)) ? 0xFF : 0x00, p8 );
  224.               odata= &odata[p16];
  225.             }
  226.           }
  227.           else /* !pp bit */
  228.           {
  229.             if(i->PlanePick & (1<<d))
  230.               idata= &idata[p16];
  231.  
  232.             if( !(optimode & OPT_CRITICAL) )
  233.             {
  234.               memset( (char *)odata, (p10 & (1<<d)) ? 0xFF : 0x00, p8 );
  235.               odata= &odata[p16];
  236.               pp |= (1<<d);
  237.               p10 &= ~(1<<d);
  238.             }
  239.           }
  240.         }
  241.  
  242.         if(D>=3 && D<P) /* no need to check OPT_NOEXPAND sice P is < D if set */
  243.         {
  244.           UWORD *p;
  245.  
  246.           if( p= (UWORD *)malloc(p8) )
  247.           {
  248.  
  249.             if( (optimode & OPT_REMAPV37) && p10<=7 )
  250.             {
  251.               /*
  252.                   REMAP:  Make colors 4-7 become the last 4 in the palette
  253.  
  254.                   Algo: (1) OR together all planes > 2,
  255.                         (2) invert the result,
  256.                         (3) AND it with plane 2 and
  257.                         (4) OR the result with all planes > 2
  258.  
  259.                   Note: There is no need to expand the image data if p10 &~ %111 != 0
  260.               */
  261.  
  262.               /* move to plane 2 */
  263.  
  264.               idata= i->ImageData;
  265.  
  266.               for(d=0; d<2; d++)
  267.                 if(i->PlanePick & (1<<d))
  268.                   idata= &idata[p16];
  269.  
  270.               if(i->PlanePick & (1<<2))
  271.               {
  272.                 memcpy((char *)p, (char *)idata, p8);
  273.                 idata= &idata[p16];
  274.               }
  275.               else memset( (char *)p, (p10 & (1L<<2)) ? 0xFF : 0x00, p8 );
  276.  
  277.               /* or planes 3..D, invert them, AND the result with plane 2 */
  278.  
  279.               for(d=3; d<D; d++)
  280.               {
  281.                 if(i->PlanePick & (1<<d))
  282.                 {
  283.                   memandnot( (char *)p, (char *)idata, p8 );
  284.                   idata= &idata[p16];
  285.                 }
  286.                 /* else bit d of i->PlaneOnOff is 0 --> no-op */
  287.               }
  288.  
  289.               /* move to plane 3 */
  290.  
  291.               odata= o->ImageData;
  292.  
  293.               for(d=0; d<3; d++)
  294.                 if(pp & (1<<d))
  295.                   odata= &odata[p16];
  296.  
  297.               for(d=3; d<P; d++)
  298.               {
  299.                 if( d>=D || pp & (1<<d) )
  300.                 {
  301.                   memor( (char *)odata, (char *)p, p8 );
  302.                   odata= &odata[p16];
  303.                   pp |= (1<<d);
  304.                 }
  305.               }
  306.             }
  307.  
  308.             else /* !REMAPV37 */
  309.             {
  310.               /*
  311.                   EXPAND:  Remap the last 4 colors of i to the last 4 colors of o
  312.  
  313.                   Algo: (1) OR together all planes but the last
  314.                         (2) AND the result with the last plane
  315.                         (3) set the result in all new planes
  316.  
  317.                   Note: if any plane of i but the last is entirely 1 then we can
  318.                         simply copy the last plane of i to all new planes in o
  319.               */
  320.  
  321.               idata= i->ImageData;
  322.  
  323.               if( p10 &~ (1<<(D-1)) == 0)
  324.               {
  325.                 memset( (char *)p, 0x00, p8 );
  326.  
  327.                 for(d=0; d<D-1; d++)
  328.                 {
  329.                   if(i->PlanePick & (1<<d))
  330.                   {
  331.                     memor( (char *)p, (char *)idata, p8 );
  332.                     idata= &idata[p16];
  333.                   }
  334.                 }
  335.                 /* else plane d is entirely 0 */
  336.  
  337.                 if( i->PlanePick & (1<<(D-1)) )
  338.                   memand( (char *)p, (char *)idata, p8 );
  339.                 /* else the last plane is entirely 1 */
  340.               }
  341.               else /* move to the last plane */
  342.               {
  343.                 for(d=0; d<D-1; d++)
  344.                   if(i->PlanePick & (1<<d))
  345.                     idata= &idata[p16];
  346.  
  347.                 if( i->PlanePick & (1<<(D-1)) )
  348.                   memcpy( (char *)p, (char *)idata, p8 );
  349.                 else
  350.                   memset( (char *)p, 0xFF, p8 );
  351.               }
  352.  
  353.               /* move to plane D */
  354.  
  355.               odata= o->ImageData;
  356.  
  357.               for(d=0; d<D; d++)
  358.                 if(pp & (1<<d))
  359.                   odata= &odata[p16];
  360.  
  361.               for(d=D; d<P; d++)
  362.               {
  363.                 memcpy( (char *)odata, (char *)p, p8 );
  364.                 odata= &odata[p16];
  365.                 pp |= (1<<d);
  366.               }
  367.  
  368.             }
  369.  
  370.             free(p);
  371.           }
  372.           else /* !p --> panic! */
  373.           {
  374.             FreeMem(o->ImageData,osize);
  375.             FreeMem(o,sizeof(struct Image));
  376.             o= (struct Image *)0L;
  377.           }
  378.         }
  379.  
  380.         o->Depth= P;
  381.         o->PlanePick= pp;
  382.         o->PlaneOnOff= p10;
  383.  
  384.       }
  385.       else /* !odata */
  386.       {
  387.         FreeMem(o,sizeof(struct Image));
  388.         o= (struct Image *)0L;
  389.       }
  390.     }
  391.   }
  392.  
  393.   if(optimode & OPT_VERBOSE)
  394.   {
  395.     if(o && o!=i)
  396.       printf(" -> (%d,%d,%d)", o->Depth, o->PlanePick, o->PlaneOnOff);
  397.     putchar('\n');
  398.   }
  399.  
  400.   return o;
  401. }
  402.  
  403. /**/
  404.  
  405. static char *tackon(char *pname, char *fname)
  406. {
  407.   char *buf= (char *)malloc(strlen(pname)+strlen(fname)+2);
  408.  
  409.   if(buf)
  410.   {
  411.     register char *s= buf;  *s= '\0';
  412.  
  413.     if(pname)
  414.     {
  415.       register int n= 0;
  416.  
  417.       while( *pname )
  418.         n++, *s++= *pname++;
  419.  
  420.       if( n>0 && buf[n-1]!=':' && buf[n-1]!='/' )
  421.         *s++ = '/';
  422.     }
  423.  
  424.     if(fname) while( *fname )
  425.       *s++ = *fname++;
  426.  
  427.     *s= '\0';
  428.   }
  429.  
  430.   return buf;
  431. }
  432.  
  433. /* main, opticon(), and doall() share the following vars */
  434.  
  435. static char *whoami;
  436. static LONG args[8] = { 0,0,0,0,0,0,0,0 };
  437. WORD numplanes= 0;
  438. int optiflags= 0;
  439.  
  440. int opticon(char *fname)
  441. {
  442.   int rc= RETURN_OK;
  443.  
  444.   /* We initially assume `fname' to be or to have an icon. */
  445.  
  446.   char *iname= (char *)strdup(fname);
  447.  
  448.   if(optiflags & OPT_VERBOSE)
  449.     printf("opticon  `%s'\n",fname);
  450.  
  451.   if(iname)
  452.   {
  453.     struct DiskObject *icon;
  454.  
  455.     if( (icon= GetDiskObject(iname)) == NULL )
  456.     {
  457.       size_t x= strlen(iname) - 5;
  458.  
  459.       if(x>0 && !stricmp(&(iname[x]),".info"))
  460.       {
  461.         iname[x]= '\0';
  462.         icon= GetDiskObject(iname);
  463.       }
  464.     }
  465.  
  466.     if(icon)
  467.     {
  468.       struct Gadget *g= &icon->do_Gadget;
  469.  
  470.       struct Image *ogr, *osr;
  471.       int modified= 0;
  472.  
  473.       ogr= osr= (struct Image *)0L;
  474.  
  475.       if(g->GadgetRender && (g->Flags & GFLG_GADGIMAGE))
  476.       {
  477.         struct Image *i= (struct Image *)g->GadgetRender;
  478.  
  479.         if(optiflags & OPT_VERBOSE)
  480.           printf("         :normal   "), fflush(stdout);
  481.  
  482.         if( ogr= optimize_image(i,numplanes,optiflags) )
  483.         {
  484.           if(ogr != i)
  485.           {
  486.             g->GadgetRender= (APTR)ogr;
  487.             ++modified;
  488.           }
  489.           else ogr= (struct Image *)0L; /* don't free ogr */
  490.  
  491.           if(g->SelectRender && (g->Flags & GFLG_GADGHIMAGE))
  492.           {
  493.             i= (struct Image *)g->SelectRender;
  494.  
  495.             if(optiflags & OPT_VERBOSE)
  496.               printf("         :selected "), fflush(stdout);
  497.  
  498.             if( osr= optimize_image(i,numplanes, optiflags) )
  499.             {
  500.               if(osr != i)
  501.               {
  502.                 g->SelectRender= (APTR)osr;
  503.                 ++modified;
  504.               }
  505.               else osr= (struct Image *)0L; /* don't free osr */
  506.             }
  507.             else
  508.             {
  509.               fprintf(stderr,"%s: %s.info: not enough free memory to optimize the selected image\n",whoami,iname);
  510.               rc= ERROR_NO_FREE_STORE;
  511.             }
  512.           }
  513.         }
  514.         else
  515.         {
  516.           fprintf(stderr,"%s: %s.info: not enough free memory to optimize the normal image\n",whoami,iname);
  517.           rc= ERROR_NO_FREE_STORE;
  518.         }
  519.       }
  520.  
  521.       /* SMART/S */
  522.  
  523.       if( rc == RETURN_OK && args[6] && (icon->do_Type == WBDRAWER || icon->do_Type == WBGARBAGE) )
  524.       {
  525.         BPTR lock= Lock(iname,ACCESS_READ);
  526.  
  527.         if( BADDR(lock) )
  528.           UnLock(lock);
  529.  
  530.         else
  531.         {
  532.           icon->do_Type = WBTOOL;
  533.           ++modified;
  534.         }
  535.       }
  536.  
  537.       if( modified && rc == RETURN_OK )
  538.       {
  539.         if( !PutDiskObject(iname,icon) )
  540.           PrintFault(rc= IoErr(), iname);
  541.       }
  542.  
  543.       if(ogr) ogr= free_image(ogr);
  544.       if(osr) osr= free_image(osr);
  545.  
  546.       FreeDiskObject(icon);
  547.     }
  548.     else /* !icon */
  549.     {
  550.       PrintFault(rc= IoErr(), iname);
  551.       fprintf(stderr,"%s: GetDiskObject() failed for %s[.info]\n",whoami,iname);
  552.  
  553.       if(args[7]) 
  554.         rc= RETURN_OK;  /* keep running */
  555.     }
  556.  
  557.     free(iname);
  558.   }
  559.   else /* !iname */
  560.   {
  561.     fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
  562.     rc= ERROR_NO_FREE_STORE;
  563.   }
  564.  
  565.   return rc;
  566. }
  567.  
  568.  
  569. int doall(char *pname)
  570. {
  571.   int rc= RETURN_OK;
  572.  
  573.   struct FileInfoBlock *fib= (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL);
  574.  
  575.   if(optiflags & OPT_VERBOSE)
  576.     printf("scanning `%s'\n",pname);
  577.  
  578.   if(fib)
  579.   {
  580.     /* set to 1 if we are to call opticon(pname) after UnLock() */
  581.     int optme= 0;
  582.  
  583.     BPTR lock= Lock(pname, ACCESS_READ);
  584.  
  585.     if( BADDR(lock) )
  586.     {
  587.       if( Examine(lock,fib) )
  588.       {
  589.         /* not the initial call from main() for a file with ALL */
  590.         if( (optme= (fib->fib_DirEntryType > 0) ? 0:1) == 0 )
  591.         {
  592.           while( (rc==RETURN_OK) && ExNext(lock,fib) && (IoErr() != ERROR_NO_MORE_ENTRIES) )
  593.           {
  594.             char *pcat= tackon(pname,fib->fib_FileName);
  595.  
  596.             if(pcat)
  597.             {
  598.               if(optiflags & OPT_VERBOSE)
  599.                 printf("found    `%s'\n",pcat);
  600.  
  601.               if( fib->fib_DirEntryType > 0 ) /* directory */
  602.               {
  603.                 rc= doall(pcat);
  604.               }
  605.  
  606.               else /* file */
  607.               {
  608.                 size_t x= strlen(pcat) - 5;
  609.  
  610.                 if( stricmp(&pcat[x],".info") == 0 ) /* "*.info" file */
  611.                 {
  612.                   rc= opticon(pcat);
  613.                 }
  614.               }
  615.  
  616.               free(pcat);
  617.             }
  618.             else /* !pcat */
  619.             {
  620.               fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
  621.               rc= ERROR_NO_FREE_STORE;
  622.             }
  623.           }
  624.         }
  625.       }
  626.       else PrintFault(rc= IoErr(), pname); /* Examine() failed */
  627.  
  628.       UnLock(lock);
  629.     }
  630.     else optme= 1;  /* !lock */
  631.     /*else PrintFault(rc= IoErr(), pname);*/
  632.  
  633.     if(optme && rc==RETURN_OK)
  634.       rc= opticon(pname);
  635.  
  636.     FreeDosObject(DOS_FIB,fib);
  637.   }
  638.   else /* !fib */
  639.   {
  640.     fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
  641.     rc= ERROR_NO_FREE_STORE;
  642.   }
  643.  
  644.   return rc;
  645. }
  646.  
  647.  
  648. /**/
  649.  
  650. int main(int argc, char **argv)
  651. {
  652.   struct RDArgs *a;
  653.   int rc= RETURN_OK;
  654.  
  655.   whoami= *argv;
  656.  
  657.   if( a= ReadArgs("FROM=NAME/A/M,"   /* 0 */
  658.                   "DEPTH=PLANES/N,"  /* 1 */
  659.                   "NOEXPAND/S,"      /* 2 */
  660.                   "CRITICAL/S,"      /* 3 */
  661.                   "REMAPV37/S,"      /* 4 */
  662.                   "VERBOSE/S,"       /* 5 */
  663.                   "SMART/S,"         /* 6 */
  664.                   "ALL/S",           /* 7 */
  665.                   args, NULL) )
  666.   {
  667.     char **flist= (char **)args[0];
  668.  
  669.     if(args[1])
  670.     {
  671.       if( (numplanes= (WORD)*(LONG *)(args[1])) < 1 )
  672.       {
  673.         fprintf(stderr,"%s: Illegal maximum depth %d\n",whoami,numplanes);
  674.         rc= RETURN_FAIL;
  675.       }
  676.     }
  677.  
  678.     if(flist && rc == RETURN_OK)
  679.     {
  680.       if( IconBase= (struct IconBase *)OpenLibrary(ICONNAME,36) )
  681.       {
  682.         if(args[2]) optiflags |= OPT_NOEXPAND;
  683.         if(args[3]) optiflags |= OPT_CRITICAL;
  684.         if(args[4]) optiflags |= OPT_REMAPV37;
  685.         if(args[5]) optiflags |= OPT_VERBOSE;
  686.  
  687.         for(;*flist && rc == RETURN_OK;flist++)
  688.           rc= args[7] ? doall(*flist) : opticon(*flist);
  689.  
  690.         CloseLibrary((struct Library *)IconBase);
  691.       }
  692.       else
  693.       {
  694.         fprintf(stderr,"%s: You need %s V36+",whoami,ICONNAME);
  695.         rc= RETURN_ERROR;
  696.       }
  697.     }
  698.     FreeArgs(a);
  699.   }
  700.   else /* !ReadArgs */
  701.   {
  702.     if(argc == 1)
  703.       display_version_information();
  704.     else
  705.       PrintFault(rc= IoErr(),NULL);
  706.   }
  707.  
  708.   return rc;
  709. }
  710.